package middleware

import (
	"compress/gzip"
	"github.com/gin-gonic/gin"
	"strconv"
	"strings"
)

// GZipMiddleware is used for determining if the incoming request should be served gzipped data.
// When the request `Content-Encoding` contains `gzip`, we write a gzipped response.
func GZipMiddleware(c *gin.Context) {
	w := c.Writer
	r := c.Request
	encoding := r.Header.Get("Accept-Encoding")
	if encoding == "" {
		c.Next()
		return
	}

	compress := true

	for _, n := range strings.Split(encoding, ",") {
		if (strings.Contains(n, "gzip") || strings.Contains(n, "*")) && strings.HasSuffix(n, ";q=0") {
			compress = false
			break
		}
	}

	if !compress {
		c.Next()
		return
	}

	w.Header().Set("Content-Encoding", "gzip")

	c.Writer = &gzipResponseWriter{ResponseWriter: w}
	c.Next()

	//next.ServeHTTP(gzipResponseWriter{resp: w}, r)
}

// gzipResponseWriter is a fake ResponseWriter that is responsible for compressing responses.
type gzipResponseWriter struct {
	status int
	gin.ResponseWriter
}

func (w *gzipResponseWriter) Write(b []byte) (int, error) {
	writer := gzip.NewWriter(w.ResponseWriter)
	defer writer.Close()

	n, err := writer.Write(b)
	if err != nil {
		return 0, err
	}

	w.ResponseWriter.Header().Del("Content-Length")
	w.ResponseWriter.Header().Set("Content-Length", strconv.Itoa(n))

	return n, nil
}

func (w *gzipResponseWriter) WriteHeader(i int) {
	w.status = i
	w.ResponseWriter.WriteHeader(i)
}

//func (w *gzipResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
//	hijacker, ok := w.ResponseWriter.(http.Hijacker)
//	if !ok {
//		return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
//	}
//	return hijacker.Hijack()
//}
